package ktor

import com.liftric.kvault.KVault
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.bearerAuth
import io.ktor.client.request.get
import io.ktor.client.request.patch
import io.ktor.client.request.post
import io.ktor.client.request.put
import io.ktor.client.request.setBody
import io.ktor.http.path
import ktor.models.ApiResponse
import models.Component
import models.Computer
import models.CreateComponentRequest
import models.CreateComputerRequest
import sendRequest

class KtorObjectsDataSource(
    private val httpClient: HttpClient,
    private val kVault: KVault
) {
    private val token: String
        get() = kVault.string("token") ?: ""

    // user
    suspend fun getMyComputers(): Result<List<Computer>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/computers/my")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Computer>>>().data
        }
    }

    suspend fun getMyComponents(): Result<List<Component>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/components/my")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Component>>>().data
        }
    }

    suspend fun verifyComputer(id: Int): Result<String?> {
        return sendRequest {
            httpClient.patch {
                url {
                    path("/inventory/api/computers/$id/verify")
                }
                bearerAuth(token)
            }.body<ApiResponse<String>>().data
        }
    }

    suspend fun verifyComponent(id: Int): Result<String?> {
        return sendRequest {
            httpClient.post {
                url {
                    path("/inventory/api/components/$id/verify")
                }
                bearerAuth(token)
            }.body<ApiResponse<String>>().data
        }
    }

    suspend fun computerBySerialNumber(serialNumber: String): Result<Computer?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/computers/serial/$serialNumber")
                }
                bearerAuth(token)
            }.body<ApiResponse<Computer>>().data
        }
    }

    suspend fun componentBySerialNumber(serialNumber: String): Result<Component?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/components/serial/$serialNumber")
                }
                bearerAuth(token)
            }.body<ApiResponse<Component>>().data
        }
    }

    suspend fun getComponentTypes(): Result<List<String>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/components/types")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<String>>>().data
        }
    }

    // admin/moderator

    suspend fun getComputers(): Result<List<Computer>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/computers")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Computer>>>().data
        }
    }

    suspend fun getComponents(): Result<List<Component>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/components")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Component>>>().data
        }
    }

    suspend fun getComputer(id: Int): Result<Computer?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/computers/$id")
                }
                bearerAuth(token)
            }.body<ApiResponse<Computer>>().data
        }
    }

    suspend fun getComponent(id: Int): Result<Component?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/components/$id")
                }
                bearerAuth(token)
            }.body<ApiResponse<Component>>().data
        }
    }

    suspend fun getComputersByLocation(locationId: Int): Result<List<Computer>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/locations/$locationId/computers")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Computer>>>().data
        }
    }

    suspend fun getComponentsByLocation(locationId: Int): Result<List<Component>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/locations/$locationId/components")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Component>>>().data
        }
    }

    suspend fun getComponentsByComputer(computerId: Int): Result<List<Component>?> {
        return sendRequest {
            httpClient.get {
                url {
                    path("/inventory/api/computers/$computerId/components")
                }
                bearerAuth(token)
            }.body<ApiResponse<List<Component>>>().data
        }
    }

    suspend fun createComputer(computer: CreateComputerRequest): Result<Int?> {
        return sendRequest {
            httpClient.post {
                url {
                    path("/inventory/api/computers")
                }
                bearerAuth(token)
                setBody(computer)
            }.body<ApiResponse<Int>>().data
        }
    }

    suspend fun createComponent(component: CreateComponentRequest): Result<Int?> {
        return sendRequest {
            httpClient.post {
                url {
                    path("/inventory/api/components")
                }
                bearerAuth(token)
                setBody(component)
            }.body<ApiResponse<Int>>().data
        }
    }

    suspend fun updateComputer(id: Int, computer: CreateComputerRequest): Result<Int?> {
        return sendRequest {
            httpClient.put {
                url {
                    path("/inventory/api/computers/$id")
                }
                bearerAuth(token)
                setBody(computer)
            }.body<ApiResponse<Int>>().data
        }
    }

    suspend fun updateComponent(id: Int, component: CreateComponentRequest): Result<String?> {
        return sendRequest {
            httpClient.put {
                url {
                    path("/inventory/api/components/$id")
                }
                bearerAuth(token)
                setBody(component)
            }.body<ApiResponse<String>>().data
        }
    }

    suspend fun deleteComputer(id: Int): Result<String?> {
        return sendRequest {
            httpClient.post {
                url {
                    path("/inventory/api/computers")
                }
                bearerAuth(token)
                setBody(id)
            }.body<ApiResponse<String>>().data
        }
    }

    suspend fun deleteComponent(id: Int): Result<String?> {
        return sendRequest {
            httpClient.post {
                url {
                    path("/inventory/api/components")
                }
                bearerAuth(token)
                setBody(id)
            }.body<ApiResponse<String>>().data
        }
    }
}